package com.ericsson.enap.modules.autoCheck.thread;

import com.ericsson.enap.modules.autoCheck.entity.AutoCheck;
import com.ericsson.enap.modules.autoCheck.entity.AutoCheckItem;
import com.ericsson.enap.modules.autoCheck.entity.AutoCheckKpiDetail;
import com.ericsson.enap.modules.autoCheck.entity.AutocheckParam;
import com.ericsson.enap.modules.autoCheck.entity.NetAutoCheck;
import com.ericsson.enap.modules.autoCheck.entity.VisExcel;
import com.ericsson.enap.modules.autoCheck.entity.VisExcelModuleDetail;
import com.ericsson.enap.modules.autoCheck.service.EopsTemplateScheduleService;
import com.ericsson.enap.modules.autoCheck.service.IEopsTemplateExecuteService;
import com.ericsson.enap.modules.enm.entity.EnipEnmKpiAlarmCondition;
import com.ericsson.enap.modules.enm.service.IEnipEnmKpiAlarmConditionService;
import com.ericsson.enap.modules.kpi.entity.EnipKpiDataResult;
import com.ericsson.enap.modules.procLog.entity.EnipAlarmPlatformConfig;
import com.ericsson.mq.constants.RabbitMqConsts;
import com.ericsson.mq.domain.EnipKpiResult;
import org.slf4j.Logger;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class AutoCheckExecuteCmdThread implements Runnable{

	private Logger log;
	private String fetchDate;
	private CountDownLatch latch;
	private NetAutoCheck net;
	private EopsTemplateScheduleService scheduleService;
	private List<VisExcelModuleDetail> visExcelModuleDetails;
	private String tpXmlPathTxt;
	private List<VisExcelModuleDetail> moduleDetailList;
	private List<EnipAlarmPlatformConfig> configList;
	private List<VisExcel> curIntervalTemplates;
	private List<AutocheckParam> paramList;
	private MongoTemplate mongoTemplate;
	private IEopsTemplateExecuteService autoCheckParseTemplate;
	private List<EnipEnmKpiAlarmCondition> enipEnmKpiAlarmConditions;
	private RabbitTemplate rabbitTemplate;
	private String interval;

	public AutoCheckExecuteCmdThread(NetAutoCheck net, List<VisExcelModuleDetail> visExcelModuleDetails,
									 EopsTemplateScheduleService scheduleService, CountDownLatch latch, String fetchDate,
									 Logger log, String tpXmlPathTxt, List<VisExcelModuleDetail> moduleDetailList, List<EnipAlarmPlatformConfig> configList, List<VisExcel> curIntervalTemplates,
									 List<AutocheckParam> paramList, MongoTemplate mongoTemplate, IEopsTemplateExecuteService autoCheckParseTemplate,List<EnipEnmKpiAlarmCondition> enipEnmKpiAlarmConditions,RabbitTemplate rabbitTemplate,String interval) {
		this.net = net;
		this.visExcelModuleDetails = visExcelModuleDetails;
		this.fetchDate = fetchDate;
		this.scheduleService = scheduleService;
		this.latch = latch;
		this.log = log;
		this.tpXmlPathTxt = tpXmlPathTxt;
		this.moduleDetailList = moduleDetailList;
		this.configList = configList;
		this.curIntervalTemplates = curIntervalTemplates;
		this.paramList = paramList;
		this.mongoTemplate = mongoTemplate;
		this.autoCheckParseTemplate = autoCheckParseTemplate;
		this.enipEnmKpiAlarmConditions = enipEnmKpiAlarmConditions;
		this.rabbitTemplate=rabbitTemplate;
		this.interval = interval;
	}

	public AutoCheckExecuteCmdThread() {

	}

	@Override
	public void run() {
		try {
			dotask();
		} catch (Exception e) {
			log.error("dotask error", e);
		} finally {
			latch.countDown();
		}

	}

	private void dotask() {
		log.info("===============sub thread ====netId:" + net.getId() + " run start");
		//Map<Integer,AutocheckMaxtime> timeMap = scheduleService.listAutoCheckMaxtime().stream().collect(Collectors.toMap(AutocheckMaxtime::getExcelId, e->e));

		for (VisExcelModuleDetail moduleDetail : visExcelModuleDetails) {
			String command = "/usr/bin/perl -w /opt/Ericsson/core/bin/eops.pl";
			command += " -ip " + net.getIp4() + " -user " + net.getUsername() + " -password '" + net.getPassword()
					+ "' -conf_file " + tpXmlPathTxt + moduleDetail.getExcelId() + "_"
					+ moduleDetail.getModuleId() + ".txt -rootpassword '" + net.getRootPassword() + "'";
			log.info("netId========" + net.getId() + "command======" + command);

			//判断是否是巡检指标模板

			List<AutocheckParam> params = paramList.stream().filter(e -> e.getExcelId()== moduleDetail.getExcelId().intValue()).collect(Collectors.toList());
			System.out.println(params.size() + "**********************" + moduleDetail.getModuleId());
			if("4".equals(moduleDetail.getTemplateType()) && params.size() > 0) {
				//自动巡检kpi
				System.out.println("autocheck kpi....");
				execAutoTemplateCheckKpi(command, net, params,moduleDetail);



			}
			if("3".equals(moduleDetail.getTemplateType())) {
				//查询是否为告警模板
				List<EnipAlarmPlatformConfig> configs = configList.stream().filter(e -> e.getTemplateId().intValue()== moduleDetail.getExcelId().intValue()).collect(Collectors.toList());
				AutoCheck ac = null;
				if(configs.size() <= 0) {
					//普通巡检模板
					System.out.println("autocheck ....");
					ac = execAutoTemplateCheckCmd(command, net.getId(), moduleDetail.getExcelId(), moduleDetail.getModuleId());
				} else {
					//告警模板  //目前作废
					ac = execAutoTemplateCheckAlarmCmd(command, net.getId(), moduleDetail.getExcelId(), moduleDetail.getModuleId());
				}
				scheduleService.insertAutoCheck(ac);
				for (AutoCheckItem e : ac.getAutoCheckItemList()) {
					e.setAutocheckId(ac.getId());
				}

				scheduleService.insertAutoCheckItem(ac.getAutoCheckItemList());

				//查询当前巡检记录，如果失败发告警
				AutoCheckItem item = new AutoCheckItem();
				item.setAutocheckId(ac.getId());
				List<AutoCheckItem> itemList = scheduleService.selectAutoCheckItem(item);
				System.out.println("autocheck --------------------" + itemList.size());
				Map<Long,EnipEnmKpiAlarmCondition> enipEnmKpiAlarmConditionMap=
						enipEnmKpiAlarmConditions.stream().filter(e->e.getDoWithType()==5).
								collect(Collectors.toMap(EnipEnmKpiAlarmCondition::getKpiId,a->a ,(k1,k2)->k1));
				//只有结果为0的是失败，发送告警
				for(AutoCheckItem aci : itemList) {
					//if(aci.getItemResult().intValue() != 1) {  //1为成功
					if(enipEnmKpiAlarmConditionMap != null && enipEnmKpiAlarmConditionMap.size()>0) {
						EnipEnmKpiAlarmCondition condition = enipEnmKpiAlarmConditionMap.get(Long.valueOf(aci.getDetailItemId().longValue()));
						if(condition != null) {
							//发送告警
							EnipKpiResult enipKpiResult=new EnipKpiResult();
							enipKpiResult.setInterval(Integer.parseInt(this.interval));
							enipKpiResult.setKpiCreateTime(this.fetchDate);
							enipKpiResult.setKpiId(Long.valueOf(aci.getDetailItemId().intValue()));
							enipKpiResult.setNetId(Long.valueOf(net.getId().intValue()));
							enipKpiResult.setValue(aci.getItemResult().intValue() != 1 ? "0" : "1");
							enipKpiResult.setBizType(condition.getDoWithType());
							enipKpiResult.setAutoCheckItemId(aci.getId());
							System.out.println("xunjian--------------------");
							System.out.println(enipKpiResult);
							rabbitTemplate.convertAndSend(RabbitMqConsts.EXCHANGE_NAME,RabbitMqConsts.DIRECT_ROUTING_KEY_ALARM,enipKpiResult);

						}
					}
					//}
				}

			}

		}
		log.info("================= AutoCheckTemplateServiceTask end  ========");
	}

	public AutoCheckKpiDetail execAutoTemplateCheckKpi(String command, NetAutoCheck net, List<AutocheckParam> params,VisExcelModuleDetail moduleDetail) {
		Process proc = null;
		String[] cmd = new String[3];
		cmd[0] = "sh";
		cmd[1] = "-c";
		cmd[2] = command;
		BufferedReader br = null;
		String line = null;
		AutoCheckKpiDetail detail = new AutoCheckKpiDetail();
		Map<String,String> itemMap = detail.getItemMap();

		Map<Long,EnipEnmKpiAlarmCondition> enipEnmKpiAlarmConditionMap=
				enipEnmKpiAlarmConditions.stream().filter(e->e.getDoWithType()==3||e.getDoWithType()==4).
						collect(Collectors.toMap(EnipEnmKpiAlarmCondition::getKpiId,a->a ,(k1,k2)->k1));

		try {
			proc = Runtime.getRuntime().exec(cmd);// 测试时需要注释掉
			br = new BufferedReader(new InputStreamReader(proc.getInputStream(), Charset.forName("UTF-8")), 10 * 1024 * 1024);// 测试时需要注释掉

			//br = readFile("F:/autocheck.txt");//测试代码

			while ((line = br.readLine()) != null) {
				if(line.contains("SYSTEM-PRINT") ) {
					String finalLine = line;
					String kpiVal = null;
					List<AutocheckParam> itemList = params.stream().filter(e -> finalLine.contains(e.getItemName().substring(13).trim())).collect(Collectors.toList());
					if(itemList.size() > 0) {
						AutocheckParam acp = itemList.get(0);

						while((line = br.readLine()) != null) {
							if(line.contains("<font color") && line.contains("VALUE IS")) {
								//String value = line.substring(line.indexOf("VALUES")+7,line.lastIndexOf("</")).replaceAll(":","").trim();
								String value = line.substring(line.lastIndexOf(":")+1).replace(":","").trim();
								kpiVal = value;
								itemMap.put(String.valueOf(acp.getId().intValue()),value);
								break;
							}
						}
					}

					//检查是否有告警
					List<VisExcelModuleDetail> moduleDetails = findList(moduleDetail.getExcelId(),moduleDetail.getModuleId(),finalLine);
					if(kpiVal != null && moduleDetails.size() > 0) {
						VisExcelModuleDetail d = moduleDetails.get(0);
						if(enipEnmKpiAlarmConditionMap != null && enipEnmKpiAlarmConditionMap.size()>0) {
							EnipEnmKpiAlarmCondition condition = enipEnmKpiAlarmConditionMap.get(Long.valueOf(d.getId().longValue()));
							if(condition != null) {
								//发送告警
								EnipKpiResult enipKpiResult=new EnipKpiResult();
								enipKpiResult.setInterval(Integer.parseInt(this.interval));
								enipKpiResult.setKpiCreateTime(this.fetchDate);
								enipKpiResult.setKpiId(Long.valueOf(d.getId().intValue()));
								enipKpiResult.setNetId(Long.valueOf(net.getId().intValue()));
								enipKpiResult.setValue(kpiVal);
								enipKpiResult.setBizType(condition.getDoWithType());
								String queue = "";
								if(condition.getDoWithType().intValue() == 3) {
									queue = RabbitMqConsts.DIRECT_ROUTING_KEY_ALARM;
								} else if(condition.getDoWithType().intValue() == 4) {
									queue = RabbitMqConsts.DIRECT_ROUTING_KEY_EOPS;
								}
								rabbitTemplate.convertAndSend(RabbitMqConsts.EXCHANGE_NAME,queue,enipKpiResult);

							}
						}

					}
				}
			}
			if(itemMap.size()>0) {
				detail.setDateTime(this.fetchDate);
				detail.setNetid(String.valueOf(net.getId().intValue()));
				detail.setNetName(net.getName());
				detail.setPoolid(String.valueOf(net.getPoolId().intValue()));
				this.mongoTemplate.insert(detail, getCollectionName());

			}
			br.close();
			proc.waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (proc != null) {
				proc.destroy();
			}
		}
		return detail;

	}


	public AutoCheck execAutoTemplateCheckCmd(String command, Integer netId, int excelId, int moduleId) {

		AutoCheck autoCheck = autoCheckParseTemplate.execAutoTemplateCheckCmd(command,netId,excelId,moduleId,this.fetchDate,this.moduleDetailList);
		return autoCheck;
		/*Process proc = null;
		String[] cmd = new String[3];
		cmd[0] = "sh";
		cmd[1] = "-c";
		cmd[2] = command;
		BufferedReader br = null;
		String line = null;
		AutoCheck autoCheck = new AutoCheck();
		autoCheck.setCheckTime(this.fetchDate);
		autoCheck.setNetId(netId);
		autoCheck.setVisexcelId(excelId);
		try {
			proc = Runtime.getRuntime().exec(cmd);// 测试时需要注释掉
			br = new BufferedReader(new InputStreamReader(proc.getInputStream(), Charset.forName("UTF-8")), 10 * 1024 * 1024);// 测试时需要注释掉

			*//*if(excelId == 77) {
				br = readFile("F:/amf.txt");//测试代码
			} else if(excelId == 89) {
				br = readFile("F:/smf.txt");//测试代码
			}*//*
			Thread.sleep(200);
			boolean isValidLog = false;
			boolean isEnd = false;
			StringBuilder sb = new StringBuilder();
			while ((line = br.readLine()) != null) {
				if(line.contains("SYSTEM-PRINT") || isEnd) {

					if(sb.length() > 0) {
						AutoCheckItem item1 = autoCheck.getAutoCheckItemList().get(autoCheck.getAutoCheckItemList().size()-1);
						item1.setCheckLog(sb.toString());

						//判断日志状态 全不成功 :0, 全部成功 :1 , 部分成功: 2
						int totalCount = getTotalItem(sb.toString(),"<font color"); //总条数
						int errorCount = getTotalItem(sb.toString(),"#f00000"); //失败数
						int successCount = getTotalItem(sb.toString(),"#00b000"); //成功数

						if(totalCount == successCount) {
							//全部成功
							item1.setItemResult(1);
						} else if(totalCount == errorCount) {
							//全部失败
							item1.setItemResult(0);
						} else {
							//部分成功
							item1.setItemResult(2);
						}
						sb.setLength(0);
						isValidLog = false;
						if(isEnd) break;
					}

					List<VisExcelModuleDetail> subDetail = findList(excelId,moduleId,line);
					if(subDetail != null && subDetail.size()>0) {
						isValidLog = true;
						AutoCheckItem item = new AutoCheckItem();
						VisExcelModuleDetail d = subDetail.get(0);
						item.setNetId(netId);
						item.setVisexcelId(excelId);
						item.setDetailItemId(d.getId());
						item.setItemName(d.getConfCmd().substring(13));
						autoCheck.getAutoCheckItemList().add(item);
					}

				} else {
					if(isValidLog) {
						if(line.contains("EOPS RUN SUCCESS")) {
							isEnd = true;
							continue;
						} else if(line.contains("EOPS RUN STATUS")) {
							continue;
						}
						sb.append(line).append("</br>");
					}
				}

			}
			br.close();
			proc.waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (proc != null) {
				proc.destroy();
			}

		}
		calcCheckResult(autoCheck);
		return autoCheck;*/
	}

	public AutoCheck execAutoTemplateCheckAlarmCmd(String command, Integer netId, int excelId, int moduleId) {
		Process proc = null;
		String[] cmd = new String[3];
		cmd[0] = "sh";
		cmd[1] = "-c";
		cmd[2] = command;
		BufferedReader br = null;
		String line = null;
		AutoCheck autoCheck = new AutoCheck();
		autoCheck.setCheckTime(this.fetchDate);
		autoCheck.setNetId(netId);
		autoCheck.setVisexcelId(excelId);
		StringBuilder sb = new StringBuilder();

		try {
			proc = Runtime.getRuntime().exec(cmd);// 测试时需要注释掉
			br = new BufferedReader(new InputStreamReader(proc.getInputStream(),Charset.forName("UTF-8")), 10 * 1024 * 1024);// 测试时需要注释掉

			//br = readFile("F:/alarm.txt");//测试代码
			int checkResult = 1;
			while ((line = br.readLine()) != null) {
				if(line.contains("EOPS RUN STATUS")) {
					continue;
				}
				sb.append(line).append("</br>");
				if (line.contains("EOPS RUN SUCCESS")) {
					checkResult = 1;
				} else if (line.contains("<font color=\"red\">")) { // 异常 低于门限
					checkResult = 0;
				} else {
					checkResult = 0;
				}
			}
			AutoCheckItem item = new AutoCheckItem();
			item.setNetId(netId);
			item.setVisexcelId(excelId);
			item.setItemResult(checkResult);
			item.setCheckLog(sb.toString());
			List<VisExcel> excels = curIntervalTemplates.stream().filter(e -> e.getId().intValue() == excelId).collect(Collectors.toList());
			if(excels.size() > 0) {
				item.setItemName(excels.get(0).getName());
			}

			autoCheck.setCheckResult(checkResult);
			autoCheck.getAutoCheckItemList().add(item);
			br.close();
			proc.waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (proc != null) {
				proc.destroy();
			}

		}
		return autoCheck;
	}

	private List<VisExcelModuleDetail> findList(int excelId, int moduleId, String confCmd) {
		List<VisExcelModuleDetail> moduleList = new ArrayList<>();
		//List<VisExcelModuleDetail> moduleList = moduleDetailList.stream().filter(e -> e.getExcelId().intValue() == excelId && e.getModuleId().intValue() == moduleId && e.getConfCmd().contains("SYSTEM-PRINT") && confCmd.contains(e.getConfCmd().substring(13))).collect(Collectors.toList());
		for(VisExcelModuleDetail detail : moduleDetailList) {
			if(detail.getExcelId().intValue() == excelId && detail.getModuleId().intValue() == moduleId && detail.getConfCmd().contains("SYSTEM-PRINT")) {
				if(confCmd.contains(detail.getConfCmd().substring(13))) {
					moduleList.add(detail);
				}

			}
		}

		return moduleList;
	}

	private void calcCheckResult(AutoCheck autoCheck) {
		List<AutoCheckItem> items = autoCheck.getAutoCheckItemList();
		int totalCount = 0;
		int allErrorCount = 0;
		int allSuccessCount = 0;
		for (AutoCheckItem item : items) {
			totalCount ++;
			if(item.getItemResult().intValue() == 0) {
				//全不成功
				allErrorCount ++;
			} else if(item.getItemResult().intValue() == 1) {
				//全部成功
				allSuccessCount ++;
			} else if(item.getItemResult().intValue() == 2) {
				//部分成功
				autoCheck.setCheckResult(2);
				return;
			}
		}
		if(totalCount == allErrorCount) {
			autoCheck.setCheckResult(0);
		} else if(totalCount == allSuccessCount) {
			autoCheck.setCheckResult(1);
		} else {
			autoCheck.setCheckResult(2);
		}

	}

	private int getTotalItem(String srcText,String findText) {
		int count = 0;
		Pattern p = Pattern.compile(findText);
		Matcher m = p.matcher(srcText);
		while(m.find()) {
			count++;
		}
		return count;
	}

	public String getCollectionName() {

		String suffix="";
		switch (this.net.getType()) {
			case 1:
				suffix="amf";
				break;
			case 2:
				suffix="smf";
				break;
			case 3:
				suffix="upf";
				break;
			case 4:
				suffix="pcf";
				break;
			case 5:
				suffix="chf";
				break;
			case 6:
				suffix="hss";
				break;
			case 7:
				suffix="nrf";
				break;
			case 8:
				suffix="udm";
				break;
			case 9:
				suffix="udmudr";
				break;
			case 10:
				suffix="scp";
				break;
			case 11:
				suffix="bsf";
				break;
			case 12:
				suffix="pcfudr";
				break;
		}
		return "autocheck_16_" + suffix;

	}


	public BufferedReader readFile(String path) {
		FileInputStream fileInputStream = null;
		InputStreamReader inputStreamReader = null;
		BufferedReader reader = null;
		try {
			fileInputStream = new FileInputStream(path);
			inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
			reader = new BufferedReader(inputStreamReader);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return reader;
	}

	public static void main(String[] args) {
		String s = "<font color=\"#00b000\">MAX VALUE IS : 63";
		System.out.println(s.substring(s.lastIndexOf(":")+1).trim());
	}

}
